#include <cstdlib>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include "ringQueue.hpp"
#include "Task.hpp"

int myAdd(int x, int y)
{
    return x + y;
}

struct ThreadData
{
    RingQueue<Task> *_rq;
    std::string threadname;
};

void *consumer(void *args) // 消费
{
    sleep(1);
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task> *rq = td->_rq;
    std::string name = td->threadname;

    while (true)
    {
        Task t;
        // 1，从环形队列中拿数据
        rq->pop(&t);
        // 2，进行一定的处理 --> 当然，也不要忽略它的时间消耗问题
        std::cout << name << ": 消费数据：" << t._x << " + " << t._y << " = " << t() << std::endl;
        sleep(1);
    }
}
void *productor(void *args) // 生产
{
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task> *rq = td->_rq;
    std::string name = td->threadname;

    while (true)
    {
        // 1，构建数据或者任务对象 --> 一般从外部来 --> 不要忽略构建任务或数据的时间问题
        int x = rand() % 10 + 1;
        usleep(rand() % 1000);
        int y = rand() % 5 + 1;
        Task t(x, y, myAdd); // 制作一个简单的加法任务
        std::cout << name << ": 生产数据：" << t._x << " + " << t._y << " = ?" << std::endl;
        // 2，推送到环形队列
        rq->push(t);
    }
}

int main()
{
    srand((uint64_t)time(nullptr) ^ getpid());
    RingQueue<Task> *rq = new RingQueue<Task>(5); // 这个10可以自己修改
    // rq->debug();
    pthread_t c[3], p[2]; // 5个消费线程，3个生产线程
    for (int i = 0; i < 3; i++)
    {
        ThreadData *td = new ThreadData;
        td->_rq = rq;
        td->threadname = "消费者-" + std::to_string(i);
        pthread_create(c + i, nullptr, consumer, (void *)td);
    }
    for (int i = 0; i < 2; i++)
    {
        ThreadData *td = new ThreadData;
        td->_rq = rq;
        td->threadname = "生产者-" + std::to_string(i);
        pthread_create(p + i, nullptr, productor, (void *)td);
    }

    for (int i = 0; i < 3; i++)
        pthread_join(c[i], nullptr);
    for (int i = 0; i < 2; i++)
        pthread_join(p[i], nullptr);
    return 0;
}